<?php
/**
 * Created by PhpStorm.
 * User: hnh
 * Date: 2017/11/15
 * Time: 上午11:17
 */
namespace core\model;
use PDO;
use PDOException;
class Base{

    protected static $pdo;//pdo
    protected $table;//表名
    protected $where = [];
    protected static $priKey = [];//定义主键属性

    public function __construct($config,$table)
    {
        //自动执行连接数据库方法
        $this->connect($config);
        //将$table对应的表名赋值给$this->table属性
        $this->table = $table;
    }

    /**
     * 连接数据库方法
     */
    public function connect($config){
        if (!is_null(self::$pdo)){
            return;
        }
        $dsn = "mysql:host={$config['host']};dbname={$config['dbname']}";
        $username = $config['username'];
        $password = $config['password'];
        try{
            //尝试连接数据库,如果中间某一个参数有错,直接走进catch中
            $pdo = new PDO($dsn,$username,$password);
            //设置字符集
            $pdo->query("set names utf8");
            //将$pdo对象存储在静态变量中,让其他方法可以调用,并且,通过静态变量我们可以判断是否连接过数据库,如果连接过,就不再进行连接
            self::$pdo = $pdo;
        }catch (PDOException $e){
            die($e->getMessage());
        }
    }


    /**
     * 获取多条数据方法
     */
    public function get(){
        $stmt = $this->prepareGet();
        if(empty($this->where)){
            $stmt->execute();
        }else{
            $stmt->execute([$this->where['value']]);
        }
        $data = false;
        if($stmt){
            $data = $stmt->fetchAll(PDO::FETCH_ASSOC);
        }
        $this->data = $data;
        return $this;
    }


    /**
     * 返回get需要的pdo预处理器
     * @return mixed
     */
    protected function prepareGet()
    {
        return self::$pdo->prepare($this->getWhere());
    }

    /**
     * 将对象转换成数组
     */
    public function toArray(){
        return $this->data;
    }


    /**
     * 直接获取数组类型的数据方法
     */
    public function getArray(){
        //直接调用get方法
        $data = $this->get();
        return $data->data;
    }

    /**
     * 通过主键查询
     * @param $pri
     * @return mixed
     */
    public function find($pri){
        $priKey = $this->getPriKey();
        self::$priKey[$priKey] = $pri;//将主键名称和主键值存入属性中
        $this->where($priKey,$pri);//where条件
        $stmt = $this->prepareFind();//获取find需要的预处理
        $stmt->execute([$pri]);
        $data = $stmt->fetch(PDO::FETCH_ASSOC);
        return $data;
    }

    /**
     * 返回find需要的预处理语句
     * @return mixed
     */
    public function prepareFind()
    {
        return self::$pdo->prepare($this->getWhere());
    }

    /**
     * 获取数据表的主键名称
     */
    public function getPriKey(){
        //通过查看当前需要操作的表的表结构来找主键名称
        $sql = "desc {$this->table}";
        //需要使用pdo对象执行sql
        $result = self::$pdo->query($sql);
        $data = $result->fetchAll(PDO::FETCH_ASSOC);
        //循环$data,找到表结构中的主键名称
        $priKey = '';
        foreach ($data as $k => $v){
            if ($v['Key'] == 'PRI'){
                //如果当前数据的key字段的值等于PRI,代表当前数据是主键字段数据
                $priKey = $v['Field'];
                break;
            }
        }
        return $priKey;
    }

    /**
     * 添加数据方法
     * @param $data
     * @return mixed
     */
    public function add($data){
        $stmt = $this->prepareAdd($data);
        foreach ($data as $k=>$v) {
            $stmt->bindParam(':' . $k, $v);
        }
        return $stmt->execute();
    }

    /**
     * 添加数据的预处理器
     * @param $data
     * @return mixed
     */
    protected function prepareAdd($data){
        $fields = '';//定义字段名变量
        $fieldValues = '';//定义字段值变量
        foreach ($data as $k => $v){
            $fields .= '`'.$k . '`,';//组合字段名
            $fieldValues .= ':'.$k.', ';//组合字段值
        }
        $fields = rtrim($fields,',');//去掉字段名和字段值最后的逗号
        $fieldValues = rtrim($fieldValues,' ,');
        $sql = "INSERT INTO `{$this->table}` ({$fields}) VALUES ({$fieldValues})";
        return self::$pdo->prepare($sql);
    }

    /**
     * 修改数据方法
     * @param $data
     * @return mixed
     */
    public function edit($data){
        //在组合sql之前应该组合修改语句的 字段名=字段值 的字符串
        $fields = '';
        //获取当前表的主键名称
        $priKey = $this->getPriKey();
        //循环$data
        foreach ($data as $k => $v){
            $fields .= $k . ' = "' . $v . '",';
        }
        $fields = rtrim($fields,',');
        $sql = "update {$this->table} set {$fields} where " . $priKey . ' = ' . self::$priKey[$priKey];
        $result = self::$pdo->exec($sql);
        return $result;
    }


    /**
     * 删除通过find找到的数据
     * @return mixed
     */
    public function destroy(){
        $priKey = $this->getPriKey();
        $sql = "delete from {$this->table} where " . $priKey . ' = ' . self::$priKey[$priKey];
        $result = self::$pdo->exec($sql);
        return $result;
    }


    public function delete()
    {
        $stmt = $this->prepareDelete();
        if(!empty($this->where)){
            $stmt->bindParam(1,$this->where['value']);
        }
        return $stmt->execute();
    }

    /**
     * 删除预处理器
     * @return mixed
     */
    protected function prepareDelete(){
        $sql = $this->getWhere('DELETE FROM');
        return self::$pdo->prepare($sql);
    }



    /**
     * where方法
     */
    public function where($fieldName,$query1,$query2=null){
        if($query2 === null){//运算符号默认 ==
            $this->where['key'] = $fieldName;
            $this->where['symbol'] = '=';
            $this->where['value'] = $query1;
        }else{// 自定义运算符号
            $this->where['key'] = $fieldName;
            $this->where['symbol']= $query1;
            $this->where['value'] = $query2;
        }
        return $this;
    }

    /**
     * 返回带where的sql
     * @return string
     */
    protected function getWhere($sqlPrefix='SELECT * FROM'){
        if(empty($this->where)){
            return "{$sqlPrefix} `{$this->table}`";
        }else{
            return "{$sqlPrefix} `{$this->table}` WHERE `{$this->where['key']}` {$this->where['symbol']} ?";
        }
    }

    /**
     * query方法,用来执行获取数据sql
     */
    public function query($sql){
        //用当前pdo对象执行query方法
        $result = self::$pdo->query($sql);
        $data = $result->fetchAll(PDO::FETCH_ASSOC);
        return $data;
    }

    /**
     * exec方法是执行没有结果集的方法,返回的数据是受影响的条数
     */
    public function exec($sql){
        //用当前pdo对象执行query方法
        return self::$pdo->exec($sql);
    }


}



